//
//  Security.m
//  Chart
//
//  Created by caojun on 14/12/8.
//
//

#import "CJQuote.h"
#import "ChartSocketLogger.h"
#import "math.h"
#import <objc/runtime.h>

#import <DateTools/DateTools.h>
#import <Foundation/Foundation.h>

@implementation CJQuote

@synthesize PrevClosePx = _PrevClosePx;


+ (NSDictionary *)JSONKeyPathsByPropertyKey
{
    return @{
             @"ID":@"Ei",
             @"Market":@"Exch",
             @"MarketTradingTarget":@"ExchNm",
             @"Inst":@"Inst",
             @"AbbrName":@"InstNm",
             @"DeYear":@"DeYear",
             @"DeMonth":@"DeMonth",
             @"MaxMkOdVol":@"MaxLiOdVol",
             @"MinMkOdVol":@"MinMkOdVol",
             @"MaxLiOdVol":@"MaxLiOdVol",
             @"MinLiOdVol":@"MinLiOdVol",
             @"VolMul":@"VolMul",
             @"PriTick":@"PriTick",
             @"CrDate":@"CrDate",
             @"OpDate":@"OpDate",
             @"ExDate":@"ExDate",
             @"StDeDate":@"StDeDate",
             @"EdDeDate":@"EdDeDate",
             @"Stat":@"Stat",
             @"PosType":@"PosType",
             @"PosDateType":@"PosDateType",
             @"LongMaRatio":@"LongMaRatio",
             @"ShortMaRatio":@"ShortMaRatio",
             @"IsMain":@"IsMain",
             @"TradeTimeTs":@"TradeTimeTs"
             };
}

+ (NSValueTransformer *)TypeJSONTransformer
{
    return [MTLValueTransformer reversibleTransformerWithBlock:^id(NSNumber * value) {
        CJQuoteType myType = CJQuoteTypeFutures;
        switch (value.integerValue) {
            case 49:
                myType = CJQuoteTypeFutures;
                break;
            case 50:
                myType = CJQuoteTypeShareOption;
                break;
            case 51:
                myType =  CJQuoteTypeGroup;
                break;
            case 52:
                myType = CJQuoteTypeSpot;
                break;
            case 53:
                myType = CJQuoteTypePhase;
                break;
            case 54:
                myType = CJQuoteTypeSpotOption;
                break;
            default:
                break;
        }
        return @(myType);
    }];
}

+ (NSValueTransformer *)PosTypeJSONTransformer
{
    return [MTLValueTransformer reversibleTransformerWithBlock:^id(NSNumber * value) {
        CJPosType myType = CJPosTypeNetPosition;
        switch (value.integerValue) {
            case 49:
                myType = CJPosTypeNetPosition;
                break;
            case 50:
                myType = CJPosTypeConsolidatedPosition;
                break;
            }
        return @(myType);
    }];
}

+ (NSValueTransformer *)PosDateTypeJSONTransformer
{
    return [MTLValueTransformer reversibleTransformerWithBlock:^id(NSNumber * value) {
        CJPosDateType myType = CJPosDateTypeHistoricalPosition;
        switch (value.integerValue) {
            case 49:
                myType = CJPosDateTypeHistoricalPosition;
                break;
            case 50:
                myType = CJPosDateTypePosition;
                break;
        }
        return @(myType);
    }];
}


- (NSString *)ID{
    return _ID.description;
}

- (void)updateWithQuote: (CJQuote *)quote{
   
    unsigned int iVarCount = 0;
    Ivar *iVarList = class_copyIvarList([self class], &iVarCount);    //取得变量列表,[self class]表示对自身类进行操作
    for (int i = 0; i < iVarCount; i++) {
        Ivar var = *(iVarList + i);
        const char * varName = ivar_getName(var);//取得变量名字，将作为key
        NSString *key = [[NSString stringWithUTF8String:varName] substringFromIndex:1];
        //decode
        id varValue = [quote valueForKey:key];
        if (varValue && ![[self quoteKeyArray] containsObject:key]) {
            [self setValue:varValue forKey:key];
        }
    }
    free(iVarList);//记得释放内存
}

+ (CJQuote *)quoteWithDictionary: (NSDictionary *)dictionary{
    
    CJQuote *quote = [CJQuote new];
    [quote updateWithDictionary:dictionary];
    return quote;
}

- (BOOL)isValidID{
    return YES;
}

- (void)updateWithDictionary: (NSDictionary *)dictonary
{
    [[self quoteKeyMap] enumerateKeysAndObjectsUsingBlock:^(NSString  *_Nonnull key, NSString  *_Nonnull value, BOOL * _Nonnull stop) {
        id obj = [dictonary valueForKey:value];
        [self setValue:obj forKey:key];
    }];
    
    [[self qutoKeyMapToArray] enumerateKeysAndObjectsUsingBlock:^(NSString  *_Nonnull key, NSArray  *_Nonnull value, BOOL * _Nonnull stop) {
        
        id obj = [dictonary valueForKey:key]; //=>获取相应的array
        
        if ([obj isKindOfClass:[NSArray class]] && [((NSArray *)obj) count]) {
            [((NSArray *)obj) enumerateObjectsUsingBlock:^(id  _Nonnull subObj, NSUInteger idx, BOOL * _Nonnull stop) {
                if (idx <= value.count) {
                    [self setValue:subObj forKey:value[idx]];
                }
            }];
        }
    }];
    
    [self updateUpDropPx];
    [self updatePercentPx];
    [self updateCommitteeDiffPx];
    [self updateCommitteePercentPx];
    
}

- (void)updateUpDropPx
{
    if ( self.LatestPx == nil || self.PreSePri == nil )
    {
        return ;
    }
    
    self.UpDropPx = @([self.LatestPx doubleValue] - [self.PreSePri doubleValue]) ;
}

- (void)updatePercentPx
{
    if ( self.LatestPx == nil || self.PreSePri == nil )
    {
        return ;
    }
    self.PercentPx = @(100.0 * ([self.LatestPx doubleValue] - [self.PreSePri doubleValue]) / [self.PreSePri doubleValue]);
}


- (NSDictionary *)quoteKeyMap{
    return @{@"ID":@"Ei",
             @"AvgPx":@"AvPri",
             @"ClPx":@"ClPri",
             @"CurrDelta":@"CurrDelta",
             @"HighPx":@"HiPri",
             @"LoLiPrice":@"LoLiPrice",
             @"LowPx":@"LoPri",
             @"OpInt":@"OpInt",
             @"OpenPx":@"OpPri",
             @"LatestPx":@"LsPri",
             @"PrevClosePx":@"PreClPri",
             @"PreDelta":@"PreDelta",
             @"PreOpInt":@"PreOpInt",
             @"PreSePri":@"PreSePri",
             @"SePri":@"SePri",
             @"TrdDy":@"TrdDy",
             @"Tuov":@"Tuov",
             @"UpLiPrice":@"UpLiPrice",
             @"UpdTm":@"UpdTm",
             @"UpdTmSec":@"UpdTmSec",
             @"Vol":@"Vol"
        };
}

- (NSDictionary *)qutoKeyMapToArray {
    return @{@"BP":@[@"AskPx1",@"AskPx2",@"AskPx3",@"AskPx4",@"AskPx5"],
             @"BV":@[@"AskVolume1",@"AskVolume2",@"AskVolume3",@"AskVolume4",@"AskVolume5"],
             @"SP":@[@"BidPx1",@"BidPx2",@"BidPx3",@"BidPx4",@"BidPx5"],
             @"SV":@[@"BidVolume1",@"BidVolume2",@"BidVolume3",@"BidVolume4",@"BidVolume5"]};
}

- (NSArray *)quoteKeyArray{
    return @[@"ID",
             @"Market",
             @"MarketTradingTarget",
             @"Inst",
             @"AbbrName",
             @"IsMain",
             @"Type",
             @"DeYear",
             @"DeMonth",
             @"MaxLiOdVol",
             @"MaxMkOdVol",
             @"MinLiOdVol",
             @"MinMkOdVol",
             @"VolMul",
             @"LongMaRatio",
             @"ShortMaRatio",
             @"PriTick",
             @"CrDate",
             @"OpDate",
             @"ExDate",
             @"StDeDate",
             @"EdDeDate",
             @"Stat",
             @"PosType",
             @"PosDateType",
             @"TradeTimes",
             @"TradeTimeTs",
             @"MinuteSpan"];
}

- (NSNumber *) updateCommitteeDiffPx
{
    if ( self.BidVolume1 == nil ||  self.AskVolume1 == nil )
    {
        return nil;
    }
    double sumBid = [self.BidVolume1 doubleValue];
    
    double sumAsk = [self.AskVolume1 doubleValue];
    
    self.CommitteeDiffPx = @(sumBid - sumAsk);
    
    return self.CommitteeDiffPx;
}

- (NSNumber *) updateCommitteePercentPx
{
    [self updateCommitteeDiffPx];
    if ( self.BidVolume1 == nil || self.AskVolume1 == nil || self.CommitteeDiffPx == nil )
    {
        return nil;
    }
    
    double sumBid = [self.BidVolume1 doubleValue];
    
    double sumAsk = [self.AskVolume1 doubleValue];
    
    self.CommitteePercentPx = @((sumBid - sumAsk) / (sumBid + sumAsk));
    return self.CommitteePercentPx;
}

- (BOOL)HasVolume
{
    return YES;
}


#if 0
- (id)init
{
    self = [super init];

    _ID = nil;
    //名字
    _AbbrName = nil;
    _AskSettlType = nil;
    //重量单位
    _BidQuoteSide = nil;
    //交易时间
    _BondCategory = nil;
    _InternalCode = nil;
    _Keywords = nil;
    _Market = nil;
    //市场名 中文
    _MarketTradingTarget = nil;
    //精确到几位小数
    _MinuteSpan = nil;
    // OffSet > 1 就是有成交量，如上海金
    _OffSet = nil;
    //价格单位 （人民币之类）
    _OfferQuoteSide = nil;
    //一手为多少单位
    _Unit = @1;
    //昨结算
    _PreSettlementPx = nil;
    //昨收
    _PrevClosePx = nil;
    //权限 "ReserveString_1" = 020100010201020100010201;
    _ReserveString_1 = nil;
    //品种id 不是唯一
    _SecurityID = nil;
    _SecurityType = nil;
    _Sequence = nil;
    _StringField = nil;
    _AskPx1 = nil;
    _AskPx2 = nil;
    _AskPx3 = nil;
    _AskPx4 = nil;
    _AskPx5 = nil;
    _AskVolume1 = nil;
    _AskVolume2 = nil;
    _AskVolume3 = nil;
    _AskVolume4 = nil;
    _AskVolume5 = nil;
    _BidPx1 = nil;
    _BidPx2 = nil;
    _BidPx3 = nil;
    _BidPx4 = nil;
    _BidPx5 = nil;
    _BidVolume1 = nil;
    _BidVolume2 = nil;
    _BidVolume3 = nil;
    _BidVolume4 = nil;
    _BidVolume5 = nil;
    _AvgPx = nil;
    _OpenPx = nil;
    _HighPx = nil;
    _LowPx = nil;
    _LatestPx = nil;
    _TotalTradeAmount = nil;
    _TotalTradeVolume = nil;
    _TradeVolume = nil;
    _PreOpenPosition = nil;
    _DateTime = nil;
    _UpDropPx = nil;
    _PercentPx = nil;
    _AmplitudePx = nil;
    _CommitteeDiffPx = nil;
    _CommitteePercentPx = nil;
    return self;
}

- (void)setIDWithSecurityID:(NSString *)SecurityID
                 withMarket:(NSString *)Market {
    _SecurityID = SecurityID;
    _Market = Market;

    _ID = [NSString stringWithFormat:@"%@.%@", _Market, _SecurityID ];

}

//只是在储存有关数据的时候使用
- (NSDictionary *) toDictionary {

    NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:
   @{
      @"ID": objectOrEmptyStr(self.ID)
    }];
    NSArray *keys = @[@"PreSettlementPx",
                      @"PrevClosePx",
                      @"Market",
                      @"MarketTradingTarget",
                      @"SecurityID",
                      @"AbbrName",
                      @"MinuteSpan",
                      @"OffSet",
                      @"OfferQuoteSide",
                      @"Unit",
                      @"BidQuoteSide",
                      @"BondCategory",
                      @"ReserveString_1"];
    for (NSString *key in keys) {
        if ([self valueForKey:key]) {
            [dic setValue:[self valueForKey:key] forKey: key ];
        }
    }
    
    return [NSDictionary dictionaryWithDictionary:dic];
}

- (BOOL)isValidID
{
    return self.ID != nil && [self.ID rangeOfString:@"."].location != NSNotFound;
}

- (void)updateWithDictionary: (NSDictionary *)dictionary
{
    NSArray *keys = [self quoteKeyArray];
    if (dictionary[@"SecurityID"] && dictionary[@"Market"]){
        [self setIDWithSecurityID:dictionary[ @"SecurityID"] withMarket:dictionary[ @"Market"]];
    }
    for (NSString * key in keys) {
        if ([dictionary valueForKey:key]) {
            if ((self.AbbrName && [key isEqualToString:@"AbbrName"]) || (self.MarketTradingTarget && [key isEqualToString:@"MarketTradingTarget"]) || [key isEqualToString:@"Unit"]) {
                continue;
            }
            [self setValue:[dictionary valueForKey:key] forKey:key];
        }
    }
    [self updateUpDropPx];
    [self updatePercentPx];
    [self updateAmplitudePx];
    //会update CommitteeDiffPx
    [self updateCommitteePercentPx];

}


- (void)updateWithQuote: (CJQuote *)quote
{
    NSArray *keys = [self quoteKeyArray];
    if (quote.SecurityID && quote.Market){
        [self setIDWithSecurityID:quote.SecurityID withMarket:quote.Market];
    }
    for (NSString * key in keys) {
        if ([quote valueForKey:key]) {
            if ((quote.AbbrName && [key isEqualToString:@"AbbrName"]) || (quote.MarketTradingTarget && [key isEqualToString:@"MarketTradingTarget"]) || [key isEqualToString:@"Unit"]) {
                continue;
            }
            [self setValue:[quote valueForKey:key] forKey:key];
        }
    }
    [self updateUpDropPx];
    [self updatePercentPx];
    [self updateAmplitudePx];
    //会update CommitteeDiffPx
    [self updateCommitteePercentPx];

}

- (NSArray *)quoteKeyArray{
    return @[@"AbbrName",
             @"AskSettlType",
             @"BidQuoteSide",
             @"BondCategory",
             @"InternalCode",
             @"Keywords",
             @"MarketTradingTarget",
             @"MinuteSpan",
             @"OffSet",
             @"OfferQuoteSide",
             @"Unit",
             @"PreSettlementPx",
             @"PrevClosePx",
             @"ReserveString_1",
             @"SecurityType",
             @"Sequence",
             @"StringField",
             @"AskPx1",
             @"AskPx2",
             @"AskPx3",
             @"AskPx4",
             @"AskPx5",
             @"AskVolume1",
             @"AskVolume2",
             @"AskVolume3",
             @"AskVolume4",
             @"AskVolume5",
             @"BidPx1",
             @"BidPx2",
             @"BidPx3",
             @"BidPx4",
             @"BidPx5",
             @"BidVolume1",
             @"BidVolume2",
             @"BidVolume3",
             @"BidVolume4",
             @"BidVolume5",
             @"AvgPx",
             @"OpenPx",
             @"HighPx",
             @"LowPx",
             @"LatestPx",
             @"TotalTradeAmount",
             @"TotalTradeVolume",
             @"TradeVolume",
             @"PreOpenPosition",
             @"DateTime"];
}

+ (CJQuote *)quoteWithDictionary: (NSDictionary *)dictionary
{
    CJQuote * quote = [CJQuote new];
    [quote updateWithDictionary:dictionary];
    return quote;
}

- (NSNumber *)defaultMinuteSpan
{
    if(_MinuteSpan ==nil) {
        return @(2);
    }
    return _MinuteSpan;
}

- (NSNumber *)defaultOffSet
{
    if(_OffSet ==nil) {
        return @(1);
    }
    return _OffSet;
}

- (NSNumber *) updateUpDropPx
{
    if ( self.LatestPx == nil || self.PrevClosePx == nil )
    {
        return nil;
    }
    
    self.UpDropPx = @([self.LatestPx doubleValue] - [self.PrevClosePx doubleValue]) ;
    return self.UpDropPx;
}

- (NSNumber *) updatePercentPx
{
    if ( self.LatestPx == nil || self.PrevClosePx == nil )
    {
        return nil;
    }
    self.PercentPx = @(100.0 * ([self.LatestPx doubleValue] - [self.PrevClosePx doubleValue]) / [self.PrevClosePx doubleValue]);
    return self.PercentPx;
}

- (NSNumber *) updateAmplitudePx
{
    if ( self.HighPx == nil ||  self.LowPx == nil ||  self.PrevClosePx == nil )
    {
        return nil;
    }
    self.AmplitudePx = @(([self.HighPx doubleValue]- [self.LowPx doubleValue]) / [self.PrevClosePx doubleValue] * 100);
    return self.AmplitudePx;
}


- (BOOL) HasVolume
{
    return [self.defaultOffSet integerValue] > 1;
}

- (NSNumber *)getClientTagWidthServerId:(YTXServerId)serverId
                            withIsLogin:(BOOL)isLogin
{
    if (self.ReserveString_1 == nil) {
        return @(0);
    }
    int index = 0;
    if (isLogin) {
        switch (serverId) {
            case TT:
                index = 0;
                break;
            case JD:
            case TD:
                index = 1;
                break;
            case YG:
                index = 2;
                break;
            case SSY:
                index = 6;
                break;
            case BSY:
                index = 8;
                break;
            case EFS:
                index = 10;
                break;
            default:
                index = 0;
                break;
        }
    } else {
        switch (serverId) {
            case TT:
                index = 3;
                break;
            case JD:
            case TD:
                index = 4;
                break;
            case YG:
                index = 5;
                break;
            case SSY:
                index = 7;
                break;
            case BSY:
                index = 9;
                break;
            case EFS:
                index = 11;
                break;
            default:
                index = 0;
                break;
        }
    }
    
    if ([self.ReserveString_1 length] % 4 != 0) {
        chartSocketLog(@"CJQuote %@ ReserveString_1 length error", self.AbbrName);
        return @(0);
    }
    if ([self.ReserveString_1 length] <= index*4) {
        return @(0);
    }
    NSRange range = NSMakeRange(index*4, 4);
    NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
    f.numberStyle = NSNumberFormatterDecimalStyle;

    return [f numberFromString: [self.ReserveString_1 substringWithRange:range] ];
}

-(NSString *)description{
    return [NSString stringWithFormat:@"<dict> <key>ID</key><string>%@</string> \n \
     <key>Market</key><string>%@</string> \n \
     <key>MarketTradingTarget</key><string>%@</string> \n \
     <key>SecurityID</key><string>%@</string> \n \
     <key>AbbrName</key><string>%@</string> \n \
     <key>MinuteSpan</key><integer>%@</integer> \n \
     <key>OffSet</key><integer>%@</integer> \n \
     <key>OfferQuoteSide</key><string>%@</string> \n \
     <key>BidQuoteSide</key><string>%@</string> \n \
     <key>BondCategory</key><string>%@</string> \n \
     <key>ReserveString_1</key><string>%@</string> \n \
     </dict>",
            self.ID, self.Market, self.MarketTradingTarget, self.SecurityID, self.AbbrName, self.MinuteSpan, self.OffSet, self.OfferQuoteSide, self.BidQuoteSide, self.BondCategory, self.ReserveString_1 ];
}

- (NSNumber *)PrevClosePx {
    if ([self.Market isEqualToString:@"TPME"] || [self.Market isEqualToString:@"SZPEX"]) {
        return _PrevClosePx;
    }
    return _PreSettlementPx ?: _PrevClosePx;
}

#pragma mark NSKeyValueObserving Protocal

- (void)setLatestPx:(NSNumber *)LatestPx {
    [self willChangeValueForKey:@"LatestPx"];
    [self willChangeValueForKey:@"UpDropPx"];
    [self willChangeValueForKey:@"PercentPx"];
    _LatestPx = LatestPx;
    [self updateUpDropPx];
    [self updatePercentPx];
    [self didChangeValueForKey:@"PercentPx"];
    [self didChangeValueForKey:@"UpDropPx"];
    [self didChangeValueForKey:@"LatestPx"];
}

- (void)setPrevClosePx:(NSNumber *)PrevClosePx {
    [self willChangeValueForKey:@"PrevClosePx"];
    [self willChangeValueForKey:@"UpDropPx"];
    [self willChangeValueForKey:@"PercentPx"];
    [self willChangeValueForKey:@"AmplitudePx"];
    _PrevClosePx = PrevClosePx;
    [self updateUpDropPx];
    [self updatePercentPx];
    [self updateAmplitudePx];
    [self didChangeValueForKey:@"AmplitudePx"];
    [self didChangeValueForKey:@"PercentPx"];
    [self didChangeValueForKey:@"UpDropPx"];
    [self didChangeValueForKey:@"PrevClosePx"];
}

- (void)setHighPx:(NSNumber *)HighPx {
    [self willChangeValueForKey:@"HighPx"];
    [self willChangeValueForKey:@"AmplitudePx"];
    _HighPx = HighPx;
    [self updateAmplitudePx];
    [self didChangeValueForKey:@"AmplitudePx"];
    [self didChangeValueForKey:@"HighPx"];
}

- (void)setLowPx:(NSNumber *)LowPx {
    [self willChangeValueForKey:@"LowPx"];
    [self willChangeValueForKey:@"AmplitudePx"];
    _LowPx = LowPx;
    [self updateAmplitudePx];
    [self didChangeValueForKey:@"AmplitudePx"];
    [self didChangeValueForKey:@"LowPx"];
}

+ (BOOL)automaticallyNotifiesObserversOfLatestPx {
    return NO;
}

+ (BOOL)automaticallyNotifiesObserversOfPrevClosePx {
    return NO;
}

+ (BOOL)automaticallyNotifiesObserversOfUpDropPx {
    return NO;
}

+ (BOOL)automaticallyNotifiesObserversOfPercentPx {
    return NO;
}

+ (BOOL)automaticallyNotifiesObserversOfHighPx {
    return NO;
}

+ (BOOL)automaticallyNotifiesObserversOfLowPx {
    return NO;
}

+ (BOOL)automaticallyNotifiesObserversOfAmplitudePx {
    return NO;
}

+ (NSDictionary *)generateChartViewDictFromQuote:(CJQuote *)quote {
    if (!quote || !quote.ID || !quote.AbbrName || !quote.BondCategory) {
        return nil;
    }
    NSArray *bonds = [quote.BondCategory componentsSeparatedByString:@"-"];
    NSDate *referenceDate = [NSDate dateWithTimeIntervalSinceReferenceDate:0];
    NSNumberFormatter *numFmt = [NSNumberFormatter new];
    NSInteger openMinutes = [numFmt numberFromString:bonds.firstObject].integerValue;
    NSInteger closeMinutes = [numFmt numberFromString:bonds.lastObject].integerValue;
    NSDate *openTime = [referenceDate dateByAddingMinutes:openMinutes];
    NSDate *closeTime = [referenceDate dateByAddingMinutes:closeMinutes];
    closeTime = [self ensure:closeTime isLaterThan:openTime];

    NSMutableArray *restTimeArray = [NSMutableArray new];
    [bonds enumerateObjectsUsingBlock:^(NSString *value, NSUInteger idx, BOOL * stop) {
        if (([value rangeOfString:@";"].length != 0) && ![value isEqualToString:@"1440;0"]) {
            NSArray *periods = [value componentsSeparatedByString:@";"];
            NSDate *begin = [referenceDate dateByAddingMinutes:[numFmt numberFromString:periods.firstObject].integerValue];
            begin = [self ensure:begin isLaterThan:openTime];
            NSDate *end = [referenceDate dateByAddingMinutes:[numFmt numberFromString:periods.lastObject].integerValue];
            end = [self ensure:end isLaterThan:openTime];
            NSString *beginStr = [begin formattedDateWithFormat:@"YYYYMMdd HH:mm:ss" timeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
            NSString *endStr = [end formattedDateWithFormat:@"YYYYMMdd HH:mm:ss" timeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
            NSString *str = [NSString stringWithFormat:@"%@;%@", beginStr, endStr];
            [restTimeArray addObject:str];
        }
    }];
    NSString *restTime = [restTimeArray componentsJoinedByString:@";"];

    return @{
             @"hasVolume" : quote.HasVolume ? @"1" : @"0",
             @"toFix" : quote.MinuteSpan.stringValue,
             @"id" : quote.ID,
             @"marketType" : quote.Market,
             @"nickname" : quote.SecurityID,
             @"name" : quote.AbbrName,
             @"hasTJ": @"0",
             @"openTime" : [openTime formattedDateWithFormat:@"YYYYMMdd HH:mm:ss" timeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]],
             @"endTime" : [closeTime formattedDateWithFormat:@"YYYYMMdd HH:mm:ss" timeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]],
             @"restTime" : restTime,
             @"timeType" : [self timeTypeFromBondCategory:quote.BondCategory]
             };
}

+ (NSDate *)ensure:(NSDate *)aDate isLaterThan:(NSDate *)earliestDate {
    if ([aDate isEarlierThanOrEqualTo:earliestDate]) {
        return [aDate dateByAddingDays:1];
    }
    return aDate;
}

+ (NSString *)timeTypeFromBondCategory:(NSString *)bondCategory {
    NSDictionary * bondCategoryToTimeType = @{
                                              @"360-1440;0-240" : @"0",
                                              @"360-1440;0-360" : @"1",
                                              @"1260-1440;0-150;540-690;810-930" : @"2",
                                              @"540-1440;0-180" : @"3",
                                              @"1260-1440;0-150;540-690;810-900" : @"4",
                                              @"1200-1440;0-150;540-690;810-930" : @"5",
                                              @"480-1440;0-120" : @"6",
                                              @"360-1440;0-315": @"7",
                                              @"420-1440;0-375": @"8",
                                              @"420-1440;0-315": @"9",
                                              @"480-1440;0-375": @"10",
                                              @"540-1440;0-360": @"11"
                                              };
    
    NSString *result = bondCategoryToTimeType[bondCategory];
    if (result == nil) {
        result = @"100";
    }
    return result;
}
#endif

@end
